<?php
namespace App\Services;

use App\User;
use App\TempUser;
use App\GroupUser;
use App\UserGroup;
use App\UserRole;
use App\Role;
use Carbon\Carbon;
use App\BaseDictionary;
use DB;
use App\Lib\Util\QueryPager;

class UserService
{
    public function createSuperAdmin() {
        $user = User::create([
            'name' => config('system.init_user_name'),
            'nick_name' => config('system.init_user_nick_name'),
            'mobile' => config('system.init_user_mobile'),
            'password' => config('system.init_user_password'),
            'is_super' => BaseDictionary::$KEY_YES,
            'user_active' => User::$USER_STATUS_ACTIVE,
        ]);

        return $user;
    }

    public function getUsersByGroups(Array $groupIds)
    {
        $groupUserIds = GroupUser::whereIn('group_id', $groupIds)->get()->pluck('user_id')->toArray();

        return User::whereIn('id', $groupUserIds)
            ->where('is_super', BaseDictionary::$KEY_NO)
            ->where('user_active', User::$USER_STATUS_ACTIVE)
            ->get();
    }

    private function baseQuery()
    {
        return User::select('users.id', 'users.name', 'users.nick_name', 'users.email', 'users.mobile', 'users.user_active')
            ->where('users.is_super', BaseDictionary::$KEY_NO);
    }

    public function getUsers(Array $input, $paging = true)
    {
        $query = $this->baseQuery();

        if (!empty($input['activeStatus'])) {
            $query = $query->where('users.user_active', $input['activeStatus']);
        }

        if (!empty($input['deptId'])) {
            $query = $query->join('group_users', function ($join) {
                $join->on('users.id', '=', 'group_users.user_id');
            })->where('group_users.group_id', $input['deptId']);
        }

        if (!empty($input['roleId'])) {
            $query = $query->join('user_roles', function ($join) {
                $join->on('users.id', '=', 'user_roles.user_id');
            })->where('user_roles.role_id', $input['roleId']);
        }

        if (!empty($input['mobile'])) {
            $query->where('users.mobile', 'like' , '%'.$input['mobile'].'%');
        }

        if (!empty($input['name'])) {
            $query = $query->where(function($query) use ($input){
                $query->where('users.nick_name', 'like' , '%'.$input['name'].'%')
                     ->orWhere('users.name', 'like' , '%'.$input['name'].'%');
            });
        }

        $pager = new QueryPager($query);

        $pager->mapField('user_active', User::$USER_STATUS_MAP);

        return $paging ? $pager->doPaginate($input, 'name') :
            $pager->queryWithoutPaginate($input, 'name');
    }

    public function checkUserByMobile($mobile)
    {
        return User::where('mobile', $mobile)->first();
    }

    public function isRegVerifyCodeTooFrequency($mobile)
    {
        return !$this->isRegVerifyCodeExpired($mobile);
    }

    public function isRegVerifyCodeExpired($mobile)
    {
        $tempUser = TempUser::where('mobile', $mobile)->first();

        if(isset($tempUser)) {
            return isset($tempUser->mobile_verify_begin) &&
                Carbon::now()->diffInSeconds(Carbon::parse($tempUser->mobile_verify_begin)) > 60 ;
        }

        return true;
    }

    public function isRegVerifyCodeValid($mobile, $verifyCode)
    {
        $tempUser = TempUser::where('mobile', $mobile)->first();

        if(isset($tempUser)) {
            return $tempUser->mobile_verify_code == $verifyCode;
        }

        return false;
    }

    public function getRegisterVerifyCode($mobile)
    {
        $tempUser = TempUser::where('mobile', $mobile)->first();

        return isset($tempUser) ? $tempUser->mobile_verify_code : '';
    }

    public function sendRegisterVerifyCode($mobile)
    {
        $user = $this->checkUserByMobile($mobile);

        if(!isset($user)) {
            $tempUser = TempUser::where('mobile', $mobile)->first();

            $verifyCode = random_int(1000, 9999);

            if(isset($tempUser)) {
                $tempUser->mobile_verify_code = $verifyCode;
                $tempUser->mobile_verify_begin = Carbon::now();
                $tempUser->save();
            } else {
                $tempUser = TempUser::create([
                    'mobile' => $mobile,
                    'mobile_verify_begin' => Carbon::now(),
                    'mobile_verify_code' => $verifyCode
                ]);
            }

            $smsService = new SmsService();

            $smsService->sendMobile($mobile, config('app.name').'：您正在注册用户，验证码:'.$verifyCode);
        }
    }

    public function sendModifyVerifyCode($mobile)
    {
        $user = $this->checkUserByMobile($mobile);

        if(isset($user)) {
            $verifyCode = random_int(1000, 9999);

            $user->mobile_verify_code = $verifyCode;
            $user->mobile_verify_begin = Carbon::now();
            $user->save();

            $smsService = new SmsService();

            $smsService->sendMobile($mobile, config('app.name').'：您正在修改用户信息，验证码:'.$verifyCode);
        }
    }

    public function isModifyVerifyCodeTooFrequency($mobile)
    {
        return !$this->isModifyVerifyCodeExpired($mobile);
    }

    public function isModifyVerifyCodeExpired($mobile)
    {
        $user = User::where('mobile', $mobile)->first();

        if(isset($user)) {
            if( isset($user->mobile_verify_begin) )
                return Carbon::now()->diffInSeconds(Carbon::parse($user->mobile_verify_begin)) > 60 ;
        }

        return true;
    }

    public function isModifyVerifyCodeValid($mobile, $verifyCode)
    {
        $user = User::where('mobile', $mobile)->first();

        if(isset($user)) {
            return $user->mobile_verify_code == $verifyCode;
        }

        return false;
    }

    public function getModifyVerifyCode($mobile)
    {
        $user = User::where('mobile', $mobile)->first();

        return isset($user) ? $user->mobile_verify_code : '';
    }

    public function isUserWithMobileExistsInSameGroup($mobile, $groupId)
    {
        $group = UserGroup::findOrFail($groupId);
        $coreGroup = $group->coreOrganization();

        $user = $this->checkUserByMobile($mobile);

        if (isset($user)) {
            $groups = $user->userGroups;

            foreach ($groups as $curgroup) {
                $curCoreGroup = $curgroup->coreOrganization();

                if ($curCoreGroup->id == $coreGroup->id) {
                    return true;
                }
            }
        }

        return false;
    }

    public function saveNewUser($data, $groupId, $roleIds)
    {
        DB::transaction(function () use ($data, $groupId, $roleIds) {
            $tempUser = TempUser::where('mobile', $data['mobile'])->delete();

            $user = User::create([
                'mobile' => $data['mobile'],
                'name' => $data['name'],
                'nick_name' => $data['nick_name'],
                'password' => $data['password'],
                'email' => $data['email'],
            ]);

            $user->is_super = BaseDictionary::$KEY_NO;
            $user->user_active = User::$USER_STATUS_ACTIVE;
            $user->save();

            GroupUser::create([
                'user_id' => $user->id,
                'group_id' => $groupId,
                'is_primary_group' => BaseDictionary::$KEY_YES
            ]);

            foreach ($roleIds as $roleId) {
                if (!empty($roleId)) {
                    UserRole::create([
                        'role_id' => $roleId,
                        'user_id' => $user->id
                    ]);
                }
            }
        });
    }

    public function saveUpdateUser($data, $groupId)
    {
        DB::transaction(function () use ($data, $groupId) {
            $user = User::findOrFail($data['id']);

            $user->update([
                'nick_name' => $data['nick_name'],
                'email' => $data['email'],
                'mobile_verify_code' => null,
                'mobile_verify_begin' => null
            ]);

            if (!empty($data['password'])) {
                $user->password = $data['password'];
                $user->save();
            }

            $newGroup = UserGroup::findOrFail($groupId);
            $coreGroup = $newGroup->coreOrganization();

            $originGroups = $user->userGroups;

            $originGroupId = null;

            foreach ($originGroups as $curgroup) {
                $curCoreGroup = $curgroup->coreOrganization();

                if ($curCoreGroup->id == $coreGroup->id) {
                    $originGroupId = $curgroup->id;
                    break;
                }
            }

            GroupUser::where('user_id', $user->id)->where('group_id', $originGroupId)
                ->update(['group_id' => $groupId]);
        });
    }

    public function removeUserFromCurrent($userId, $groupId)
    {
        DB::transaction(function () use ($userId, $groupId) {
            $user = User::findOrFail($userId);

            $newGroup = UserGroup::findOrFail($groupId);
            $coreGroup = $newGroup->coreOrganization();

            $originGroups = $user->userGroups;

            $originGroupId = null;

            foreach ($originGroups as $curgroup) {
                $curCoreGroup = $curgroup->coreOrganization();

                if ($curCoreGroup->id == $coreGroup->id) {
                    $originGroupId = $curgroup->id;
                    break;
                }
            }

            if (isset($originGroupId)) {
                $roleIds = Role::where('group_id', $originGroupId)->get()->pluck('id')->toArray();

                UserRole::where('user_id', $userId)->whereIn('role_id', $roleIds)->delete();

                GroupUser::where('user_id', $userId)->where('group_id', $originGroupId)->delete();
            }
        });
    }

    public function isCurrentUserInGroup($userId, $groupId)
    {
        $group = UserGroup::findOrFail($groupId);
        $coreGroup = $group->coreOrganization();

        $user = User::findOrFail($userId);

        if (isset($user)) {
            $groups = $user->userGroups;

            foreach ($groups as $curgroup) {
                $curCoreGroup = $curgroup->coreOrganization();

                if ($curCoreGroup->id == $coreGroup->id) {
                    return true;
                }
            }
        }

        return false;
    }

    public function determineTheManagerIsCurrentUser($userId, $groupId)
    {
        $groups = UserGroup::where('manager_id', $userId)->get();

        $currentCoreGroup = UserGroup::findOrFail($groupId)->coreOrganization();

        foreach ($groups as $curgroup) {
            $curCoreGroup = $curgroup->coreOrganization();

            if ($curCoreGroup->id == $currentCoreGroup->id) {
                return true;
            }
        }

        return false;
    }

    public function addUserToCurrentGroup($userId, $groupId, $roleIds)
    {
        DB::transaction(function () use ($userId, $groupId, $roleIds) {
            $groupUser = GroupUser::where('user_id', $userId)
                ->where('group_id', $groupId)->first();

            if (!isset($groupUser)) {
                $cUserGroup = GroupUser::where('user_id', $userId)->count();

                if ($cUserGroup > 0) {
                    GroupUser::create([
                        'user_id' => $userId,
                        'group_id' => $groupId,
                        'is_primary_group' => BaseDictionary::$KEY_NO
                    ]);
                } else {
                    GroupUser::create([
                        'user_id' => $userId,
                        'group_id' => $groupId,
                        'is_primary_group' => BaseDictionary::$KEY_YES
                    ]);
                }

                foreach ($roleIds as $roleId) {
                    if (!empty($roleId)) {
                        UserRole::create([
                            'role_id' => $roleId,
                            'user_id' => $userId
                        ]);
                    }
                }
            }
        });
    }
}
